package cn.biplam.common.tools;

import java.rmi.Naming;
import java.rmi.RemoteException;

import cn.biplam.common.client.Config;
import cn.biplam.common.client.ServiceNameResolve;
import cn.biplam.common.interfaces.RmiServer;
import cn.biplam.common.paramters.index.SysParamIndex;
import cn.biplam.common.wrapper.ErrorMessage;

public abstract class RMITOOLS {

	/**
	 * 通过SNR从RMI服务器获取远程服务代理实例
	 * @param sServiceName	服务名称
	 * @return 远程服务代理实例，为null表示获取失败
	 * @throws ErrorMessage 
	 */
	public static RmiServer getInstance(String sServiceName) throws ErrorMessage{
		String sUrl=ServiceNameResolve.getUrlByName(sServiceName);
		
		if(sUrl==null){
			throw new ErrorMessage("Service connect url is null！");
		}else{
			return getInstance(sUrl, sServiceName);
		}
	}

	/**
	 * 从RMI服务器获取一个远程服务代理实例
	 * @param sIp			IP地址
	 * @param sPort			端口
	 * @param sServiceName	服务名称
	 * @return 远程服务代理实例，为null表示获取失败
	 * @throws ErrorMessage 
	 */
	public static RmiServer getInstance(String sIp,String sPort,String sServiceName) throws ErrorMessage{
		return getInstance("rmi://"+sIp+":"+sPort+"/"+sServiceName+"/",sServiceName);
	}

	/**
	 * 从RMI服务器获取一个远程服务代理实例
	 * @param sUrl 服务地址
	 * @param sServiceName	服务名称(可选)
	 * @return 远程服务代理实例，为null表示获取失败
	 */
	public static RmiServer getInstance(String sUrl,String sServiceName) throws ErrorMessage {
		RmiServer mRmiServer=null;
		try {
			mRmiServer=(RmiServer) Naming.lookup(sUrl);
			if(RMITOOLS.waitServer(mRmiServer)<0){
				mRmiServer=null;
			}
		}catch (ErrorMessage e){
			throw e;
		} catch (Exception e) {
			throw new ErrorMessage(e,"Rmi getInstance failed!");
		}
		return mRmiServer;
	}
	
	/**
	 * 取服务器引用计数，重试指定次数
	 * 		参见系统参数：
	 * 			重试次数：RETRY_NUMBER(反复尝试某个操作的总次数，默认1,0为无限次)
	 * 			重试等待步长：RETRY_WAIT_STEP(重试操作时，每次失败后增加的等待的毫秒数，默认1000)
	 * @param mInstance
	 * @return 服务器引用计数器，失败返回-1
	 * @throws ErrorMessage 
	 */
	public static int getCount(RmiServer mInstance) throws ErrorMessage{
		
		int iWait=Integer.parseInt(Config.get(SysParamIndex.Rmi_Retry_Wait_Step));
		int iRetryNumber=Integer.parseInt(Config.get(SysParamIndex.Rmi_Retry_Number));
		
		int iCount=-1;
		int iWaitStep=iWait;
		
		for(int i=0;( (i<iRetryNumber) | (iRetryNumber==0) ); ){
			if(iRetryNumber>0) i++;
			try {
				iCount=mInstance.getCount();
				i=iRetryNumber;
			} catch (RemoteException e) {
				SYSTEM.sleep(iWait);
				iWait+=iWaitStep;
				ErrorMessage  mErrorMessage = new ErrorMessage(e);
				throw mErrorMessage;
			}catch(Exception e){
				ErrorMessage  mErrorMessage = new ErrorMessage(e);
				throw mErrorMessage;
			}
		}
		return iCount;
	}

	/**
	 * 功能 等待服务器，计数器达到系统参数指定引用数以下
	 * @return 通过时的服务器引用计数,-1代表等待超时
	 * @throws ErrorMessage 
	 */
	public static int waitServer(RmiServer mInstance) throws ErrorMessage{
		int iWait=Integer.parseInt(Config.get(SysParamIndex.Rmi_Retry_Wait_Step));
		int iRetryNumber=Integer.parseInt(Config.get(SysParamIndex.Rmi_Retry_Number));
		int iMaxRmiThread=Integer.parseInt(Config.get(SysParamIndex.Rmi_Max_RMI_Thread));
		
		int iCount=-1,i=0;
		int iWaitStep=iWait;
		
		while(true){
			iCount=getCount(mInstance);
			if( (i++>=iRetryNumber) | (iCount < iMaxRmiThread)){
				break;
			}
			SYSTEM.sleep(iWait);
			iWait+=iWaitStep;
		}
		return iCount;
	}

	/**
	 * 同步上锁，直到获得锁
	 * @param mInstance
	 * @throws ErrorMessage 
	 */
	public static void lock(RmiServer mInstance) throws ErrorMessage{
		try {
			mInstance.lock();
		} catch (RemoteException e) {
			ErrorMessage  mErrorMessage = new ErrorMessage(e);
			throw mErrorMessage;
		}
	}

	/**
	 * 尝试上锁，如果发生异常，重试系统指定次数
	 * @param mInstance
	 * @return 上锁成功时的服务器引用计数,-1代表等待超时
	 * @throws ErrorMessage 
	 * @throws NumberFormatException 
	 */
	public static int trylock(RmiServer mInstance) throws NumberFormatException, ErrorMessage{
		int iWait=Integer.parseInt(Config.get(SysParamIndex.Rmi_Retry_Wait_Step));
		int iRetryNumber=Integer.parseInt(Config.get(SysParamIndex.Rmi_Retry_Number));
		
		int iCount=-1;
		int iWaitStep=iWait;

		for(int i=0;( (i<iRetryNumber) | (iRetryNumber==0) ); ){
			if(iRetryNumber>0) i++;
			try {
				if(mInstance.trylock()){
					i=iRetryNumber;
					iCount=getCount(mInstance);
				}else{
					SYSTEM.sleep(iWait);
					iWait+=iWaitStep;
				}
			} catch (RemoteException e1) {
				ErrorMessage  mErrorMessage = new ErrorMessage(e1);
				throw mErrorMessage;
			}
		}
		return iCount;
	}

	/**
	 * 尝试解锁，如果发生异常，重试系统指定次数
	 * @param mInstance
	 * @return 解锁成功时的服务器引用计数,-1代表等待超时
	 * @throws ErrorMessage 
	 * @throws NumberFormatException 
	 */
	public static int unlock(RmiServer mInstance) throws NumberFormatException, ErrorMessage{
		int iWait=Integer.parseInt(Config.get(SysParamIndex.Rmi_Retry_Wait_Step));
		int iRetryNumber=Integer.parseInt(Config.get(SysParamIndex.Rmi_Retry_Number));
		
		int iCount=-1;
		int iWaitStep=iWait;

		for(int i=0;( (i<iRetryNumber) | (iRetryNumber==0) ); ){
			if(iRetryNumber>0) i++;
			try{
				mInstance.unlock();
				i=iRetryNumber;
				iCount=getCount(mInstance);
			}catch(IllegalMonitorStateException e){
				SYSTEM.sleep(iWait);
				iWait+=iWaitStep;
				ErrorMessage  mErrorMessage = new ErrorMessage(e);
				throw mErrorMessage;
			} catch (RemoteException e) {
				ErrorMessage  mErrorMessage = new ErrorMessage(e);
				throw mErrorMessage;
			}
		}
		return iCount;
	}

	/**
	 * 探测某个服务是否可用
	 * @param mInstance
	 * @return 可用返回true,否则返回false
	 * @throws ErrorMessage 
	 */
	public static boolean feelInstance(RmiServer mInstance) throws ErrorMessage{
		return (RMITOOLS.getCount(mInstance)>0);
	}
}
